package pl.softech.gpw.stat;



public class AverageIndexes {

    /**
     * Simple Moving Average
     */
    public static double[] sma(double[] arg, int count) {
        
        double[] ret = new double[arg.length];
        double sum = 0;
        for(int i = 0; i < count - 1 && i < arg.length; i++) {
            ret[i] = arg[i];
            sum += ret[i];
        }
        
        for(int j = 0, i = count - 1; i < arg.length; i++, j++) {
            sum += arg[i];
            ret[i] = sum/count;
            sum -= arg[j];
        }
     
        return ret;
    }
    
    /**
     * Linear Weighted Moving Average
     */
    public static double[] lwma(double[] arg, int count) {
        
        double[] ret = new double[arg.length];
        int div = 0;
        double weightedSum = 0;
        double sum = 0;
        for(int i = 0; i < count - 1 && i < arg.length; i++) {
            sum += arg[i];
            ret[i] = arg[i];
            weightedSum += (i + 1) * arg[i];
            
            div += (i + 1);
        }
        
        div += count;
        
        for(int j = 0, i = count - 1; i < arg.length; i++, j++) {
            weightedSum += count * arg[i];
            ret[i] = weightedSum / div;
            sum += arg[i];
            weightedSum -= sum;
            sum -= arg[j];
        }
        
        return ret;
        
    }
    
    /**
     * Exponential Moving Average
     */
    public static double[] ema(double[] arg, double weight, int count) {
        
        double[] weights = new double[count];
        double[] ret = new double[arg.length];
        double div = 0;
        double weightedSum = 0;
        for(int i = 0; i < count - 1 && i < arg.length; i++) {
            
            weights[i] = Math.pow(weight, i + 1);
            ret[i] = arg[i];
            div += weights[i];
            weightedSum += weights[i] *  arg[i];
            
        }
        
        weights[count - 1] = Math.pow(weight, count);
        
        div += weights[count - 1];
        
        for(int j = 1, i = count - 1; i < arg.length; i++, j++) {
            
            weightedSum += weights[count - 1] * arg[i];
            ret[i] = weightedSum / div;
            
            weightedSum = 0;
            for(int k = j, l = 0;  k < j + count - 1; k++, l++) {
                
                weightedSum += weights[l] * arg[k];
                
            } 
            
        }
        
        return ret;
        
    }
    
    /**
     * Volume Weighted Moving Average
     */
    public static double[] vwma(double[] arg, double[] volume, int count) {
        
        double[] ret = new double[arg.length];
        int div = 0;
        double weightedSum = 0;
        for(int i = 0; i < count - 1 && i < arg.length; i++) {
            ret[i] = arg[i];
            weightedSum += volume[i] * arg[i];
            
            div += volume[i];
        }
        
        for(int j = 0, i = count - 1; i < arg.length; i++, j++) {
            div += volume[i];
            weightedSum += volume[i] * arg[i];
            ret[i] = weightedSum / div;
            
            weightedSum -= arg[j] * volume[j];
            div -= volume[j];
        }
        
        return ret;
        
    }
    
}
